﻿#region

using System;
using System.ComponentModel;
using System.Text.RegularExpressions;

#endregion

namespace Ymatou.CommonService
{
    /// <summary>
    ///     1.2 ... 4.5.6.7.8.9.10.11...13.14
    ///     |OP|   |IPP|IPL|ILP| ILL|   |OL|
    ///     OP--outter prev
    ///     IPP-inner prev prev
    ///     IPL-inner prev last
    ///     ILP-inner last prev
    ///     ILL-inner last last
    ///     OL--outer last
    /// </summary>
    public class PagerInfoEx : PagerInfo
    {
        public PagerInfoEx(PagerInfo info) :
            this(info.PageIndex, info.PageSize, info.RecordCount)
        {
            Initialize();
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="PagerInfo" /> class.
        /// </summary>
        /// <param name="pageIndex">当前页码(从1开始)</param>
        /// <param name="pageSize">页长</param>
        /// <param name="recordCount">记录总数</param>
        /// <Author>binbin@CHENEY-NOTEBOOK 2010/3/28 15:20</Author>
        public PagerInfoEx(int pageIndex, int pageSize, int recordCount)
            : base(pageIndex, pageSize, recordCount)
        {
            Initialize();
        }


        /// <summary>
        ///     Initializes a new instance of the <see cref="PagerInfo" /> class.
        /// </summary>
        /// <param name="pageIndex">当前页码(从1开始)</param>
        /// <param name="pageSize">页长</param>
        /// <param name="recordCount">记录总数</param>
        /// <Author>binbin@CHENEY-NOTEBOOK 2010/3/28 15:20</Author>
        public PagerInfoEx(int? pageIndex, int? pageSize, int recordCount)
            : base(pageIndex, pageSize, recordCount)
        {
            Initialize();
        }

        public string CurrentUrl { get; set; }

        public string UrlToNext
        {
            get { return GetPageUrl(PageIndex + 1); }
        }

        public bool HasOutterPrev
        {
            get { return (NeedOutter) && !IsInPrev; }
        }

        public bool HasOutterLast
        {
            get { return (NeedOutter) && InnerLastBegin < PageCount - LastCount + 1; }
        }

        public bool NeedOutter
        {
            get
            {
                return PageCount >
                       (OutterPrevCount + OutterLastCount + InnerPrevPrevCount + InnerPrevLastCount + InnerLastPrevCount +
                        InnerLastLastCount);
            }
        }

        public bool PrevDirect { get; set; }

        public bool IsInLast
        {
            get { return PageIndex >= (PageCount - LastCount + 1); }
        }

        public bool IsInOutterLast
        {
            get { return PageIndex >= (PageCount - OutterLastCount + 1); }
        }

        public int InnerBegin
        {
            get
            {
                if (IsInPrev)
                {
                    return OutterPrevCount + 1;
                }
                return InnerPrevPrevBegin;
            }
        }

        protected bool IsInPrev
        {
            get { return PageIndex < PrevCount; }
        }

        public int InnerPrevPrevBegin
        {
            get
            {
                if (IsInPrev)
                {
                    return OutterPrevCount + 1;
                }
                if (IsInLast)
                {
                    return PageCount - LastCount - InnerPrevPrevCount - InnerPrevLastCount + 1;
                }
                var i = PageIndex - InnerPrevPrevCount;
                return Math.Max(i, OutterPrevCount);
            }
        }

        public int InnerEnd
        {
            get
            {
                if (IsInLast)
                {
                    return PageCount - LastCount + 1;
                }
                var i = PageIndex + InnerPrevLastCount - 1;
                return Math.Min(i, PageCount - LastCount);
            }
        }

        public int OutterLastBegin
        {
            get { return PageCount - (OutterLastCount - 1); }
        }

        public int OutterLastEnd
        {
            get { return PageCount; }
        }

        public int InnerLastBegin
        {
            get
            {
                if (IsInLast)
                {
                    return PageCount - LastCount + 1;
                }
                if (IsInPrev)
                {
                    return InnerPrevLastEnd + 1;
                }
                return PageIndex + InnerPrevLastCount;
            }
        }

        public int InnerLastEnd
        {
            get
            {
                var i = InnerLastBegin + InnerLastCount - 1;
                return Math.Min(i, PageCount - OutterLastCount);
            }
        }

        public int OutterPrevEnd
        {
            get { return OutterPrevCount; }
        }

        [DefaultValue(2)]
        public int OutterPrevCount { get; set; }

        [DefaultValue(2)]
        public int OutterLastCount { get; set; }

        [DefaultValue(2)]
        public int InnerPrevPrevCount { get; set; }

        [DefaultValue(2)]
        public int InnerPrevLastCount { get; set; }

        [DefaultValue(2)]
        public int InnerLastPrevCount { get; set; }

        [DefaultValue(2)]
        public int InnerLastLastCount { get; set; }

        public int PrevCount
        {
            get { return OutterPrevCount + InnerPrevPrevCount + InnerPrevLastCount; }
        }

        public int LastCount
        {
            get { return InnerLastCount + OutterLastCount; }
        }

        public int InnerLastCount
        {
            get { return InnerLastPrevCount + InnerLastLastCount; }
        }

        public int LastBegin
        {
            get
            {
                var i = PageCount - LastCount + 1;
                return Math.Max(i, InnerLastBegin);
            }
        }

        /// <summary>
        ///     是否是最后一页
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is last; otherwise, <c>false</c>.
        /// </value>
        public bool IsLast
        {
            get { return PageIndex == PageCount; }
        }

        /// <summary>
        ///     是否是第一页
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is first; otherwise, <c>false</c>.
        /// </value>
        public bool IsFirst
        {
            get { return PageIndex == 1; }
        }

        public string UrlToPrev
        {
            get { return GetPageUrl(PageIndex - 1); }
        }

        public string UrlToFirst
        {
            get { return GetPageUrl(1); }
        }

        public string UrlToLast
        {
            get { return GetPageUrl(PageCount); }
        }

        public int InnerPrevLastEnd
        {
            get { return InnerPrevPrevBegin + InnerPrevPrevCount + InnerPrevLastCount - 1; }
        }

        public string PageUrlBase
        {
            get
            {
                var requestUrl = CurrentUrl;
                string pageLinkText = "";

                var pattern = string.Format(@"{0}=(\d+)|{0}=", PagePrefix.ToLower());
                Regex regexPagePattern = new Regex(pattern, RegexOptions.IgnoreCase);

                MatchCollection matchResults = regexPagePattern.Matches(requestUrl);

                if (matchResults.Count > 0)
                {
                    pageLinkText = requestUrl.Replace(matchResults[0].ToString(), "");
                }
                else
                {
                    pageLinkText = requestUrl;
                }
                return pageLinkText;
            }
        }

        [DefaultValue("p")]
        public string PagePrefix { get; set; }

        /// <summary>
        ///     Gets or sets a value indicating whether [show go].
        /// </summary>
        /// <value>
        ///     <c>true</c> if [show go]; otherwise, <c>false</c>.
        /// </value>
        [DefaultValue(false)]
        public bool ShowGo { get; set; }

        private void Initialize()
        {
            OutterPrevCount = 2;
            OutterLastCount = 2;
            InnerPrevPrevCount = 2;
            InnerPrevLastCount = 2;
            InnerLastPrevCount = 2;
            InnerLastLastCount = 2;
            PagePrefix = "p";
        }

        public virtual string GetPageUrl(int page)
        {
            var requestUrl = CurrentUrl;
            string pageLinkText = "";

            var pattern = string.Format(@"[&?]{0}=(\d+)|[&?]{0}=", PagePrefix.ToLower());
            Regex regexPagePattern = new Regex(pattern, RegexOptions.IgnoreCase);

            MatchCollection matchResults = regexPagePattern.Matches(requestUrl);

            if (matchResults.Count > 0)
            {
                pageLinkText = requestUrl.Replace(matchResults[0].ToString().Substring(1), PagePrefix.ToLower() + "=[$page$]");
            }
            else if (requestUrl.IndexOf("?") < 0)
            {
                pageLinkText = requestUrl + "?" + PagePrefix.ToLower() + "=[$page$]";
            }
            else
            {
                pageLinkText = requestUrl + "&" + PagePrefix.ToLower() + "=[$page$]";
            }
            return pageLinkText.Replace("[$page$]", page.ToString());
        }
    }
}